# -*- coding: utf-8 -*-

#builtins import
import os
import time,logging 
import gettext
import shelve

#wx import
import wx
import wx.lib.filebrowsebutton as filebrowse
import  wx.lib.mixins.listctrl  as  listmix
import  wx.wizard as wizard
import  wx.lib.rcsizer  as rcsizer
import wx.aui as aui
import wx.lib.buttonpanel as bp

#core domain object import
import pystore.core.resource_type as resource_type
import pystore.core.node_status as node_status
import pystore.core.config as config
import pystore.core.i18n as i18n
import pystore.core.nodes as nodes
from pystore.core.resource import RootResource,Dir,File,Project


#core util import
import pystore.core.framework.job as job
import pystore.core.framework.os2 as os2
import pystore.core.framework.logger as logger
import pystore.core.framework.util as util
from pystore.core.framework.logger import log

#ui import
import image_util 
import framework
import dialogs 
import memento_key
import facade2
import images

class RepositoryTree(wx.TreeCtrl):
    def __init__(self,parent):
        wx.TreeCtrl.__init__(self,parent,style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.SIMPLE_BORDER  )
        
    def OnCompareItems(self,item1Id, item2Id):
        node1 = self.GetItemData(item1Id).GetData() 
        node2 = self.GetItemData(item2Id).GetData() 
        return cmp(node1.name(),node2.name())

class LocalWorkspaceTree(wx.TreeCtrl):
    def __init__(self,parent):
        wx.TreeCtrl.__init__(self,parent,style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.SIMPLE_BORDER  )
        
    def OnCompareItems(self,item1Id, item2Id):
        node1 = self.GetItemData(item1Id).GetData() 
        node2 = self.GetItemData(item2Id).GetData() 
        return cmp(node1.name(),node2.name())

class LogViewHandler(logging.Handler):
    def __init__(self,logView):
        logging.Handler.__init__(self,logger.level)
        self.setFormatter(logging.Formatter('%(asctime)s  %(levelname)-6s>>> %(message)s'))
        self._logView=logView
    #override    
    def emit(self, record):
        try:
            msg = self.format(record)
            fs = "%s\n"
            try:
                self._logView.addText(fs % msg)
            except UnicodeError:
                self._logView.addText(fs % msg.encode("UTF-8"))
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.handleError(record)

class LogView(framework.BaseView):
    def __init__(self,parentWindow):
        framework.BaseView.__init__(self,parentWindow)
        
    #override
    def createContentPane(self,parent):
        self.textCtrl = wx.TextCtrl(parent, -1,style=wx.TE_MULTILINE)
        self.textCtrl.SetEditable(False)
        return self.textCtrl
    
    def addText(self,message):
        self.textCtrl.AppendText(message)
    
class LocalWorkspaceView(framework.BaseView):
    def __init__(self,parentWindow):
        self._workspace = facade2.localWorkspace
        self._root = self._workspace.getRoot()
        super(LocalWorkspaceView,self).__init__(parentWindow)
        
    #override
    def createContentPane(self,parent):
        self._tree = LocalWorkspaceTree(parent) 
        self._tree.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
        
        #加入所有节点
        def walkFunc(node,level):
            self._addTreeItem(node)
        self._workspace.getRoot().walk(walkFunc)
        
        return self._tree
    
    def _addTreeItem(self,node):
        """
        __addTreeItem(StoreNode node)
        
         把一个StoreNode添加到树上,每一个树节点还设置了wx.TreeItemData,内容就是node本身
         另外tree为每一个节点增加一个适配器属性用来存储TreeItemId:_adapter_RepositoryView_treeItemId 
        """
        if isinstance(node,RootResource):
            treeItemId = self._tree.AddRoot(u"root" ,data=wx.TreeItemData(node))
        else:
            treeItemId = self._tree.AppendItem(node.getParent()._adapter_RepositoryView_treeItemId, node.getName(),data=wx.TreeItemData(node))
            self._tree.SortChildren(node.getParent()._adapter_RepositoryView_treeItemId)

        node._adapter_RepositoryView_treeItemId=treeItemId

    def OnContextMenu(self,e):
        def addMenu(menu,method,text):
            menuItem=menu.Append(wx.NewId(), _t(text))
            self.getWindow().Bind(wx.EVT_MENU, method, id=menuItem.GetId())
            return menuItem
        menu = wx.Menu()
        new = wx.Menu()
        menu.AppendMenu(wx.NewId(), _t('New'), new)
        menu.AppendSeparator()
        
        newProject = addMenu(new,self.OnAddProject,_t('Project'))
        
        setProjectPath = addMenu(menu,self.OnSetProjectPath,_t('Set Project path'))

        #set Enable
        selected= self._selectedStoreNode()
        
        if selected is None:
            setProjectPath.Enable(False)
            
        self.getWindow().PopupMenu(menu)
        menu.Destroy()
        
    def _selectedStoreNode(self):
        selected=self._tree.GetSelection()
        if not selected:
            return None
        return self._tree.GetItemPyData(selected)
    
    def OnSetProjectPath(self,e):
        pass
    
    def OnAddProject(self,e):
        d = dialogs.ProjectPathDialog(self.getWindow())
        if d.ShowModal() == wx.ID_OK:
            log.info(_t('Add Project %s at: %s') % (d.getName(),d.getDir()))
            def addProject(monitor):
                self._root.getProject(d.getName()).create({'projectPath':d.getDir()},monitor)
            framework.runProgressDialog(self.getWindow(),_t('Add Project'), addProject) 
        d.Destroy()
    
class RepositoryView(framework.BaseView):
    """
        
    """
    def __init__(self,parentWindow):
        self.manager=facade2.manager

        super(RepositoryView,self).__init__(parentWindow)
        self.manager.addNodeAddedListener(self.__addTreeItem)
        
    #override
    def createContentPane(self,parent):
        self.__storeNodeTree = RepositoryTree(parent ) 
        self.__storeNodeTree.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
        
        #加入所有节点
        def walkFunc(node,level):
            self.__addTreeItem(node)
        self.manager.root.walk(walkFunc)
        
        return self.__storeNodeTree

    def OnContextMenu(self,e):
        menu = wx.Menu()
        
        def addMenu(menu,method,text):
            menuItem=menu.Append(wx.NewId(), _t(text))
            self.getWindow().Bind(wx.EVT_MENU, method, id=menuItem.GetId())
            return menuItem
        
        new = wx.Menu()
        menu.AppendMenu(wx.NewId(), _t('New'), new)
        menu.AppendSeparator()
        
        newDiskRepository = addMenu(new,self.OnAddDiskRepository,_t('Disk Repository'))
        newGmailRepository = addMenu(new,self.OnAddGmailRepository,_t('Gmail Repository'))
        new.AppendSeparator()
        newProject = addMenu(new,self.OnAddProject,_t('Project'))
        
        setProjectPath = addMenu(menu,self.OnSetProjectPath,_t('Set Project path'))
        commit = addMenu(menu,self.OnCommit,_t('Commit'))
        update = addMenu(menu,self.OnUpdate,_t('Update'))

        #set Enable
        selected= self.__selectedStoreNode()
        
        if selected is None:
            newProject.Enable(False)
            commit.Enable(False)
            update.Enable(False)
            setProjectPath.Enable(False)
            
        self.getWindow().PopupMenu(menu)
        menu.Destroy()
    
    def OnAddDiskRepository(self,e):
        d=dialogs.AddDiskRepositoryDialog(self.getWindow())
        if d.ShowModal() == wx.ID_OK:
            log.info(_t('Add Disk Repository at: %s') % (d.storeLocation()))
            d.addDiskRepository()
            
        d.Destroy()
        
    def OnAddGmailRepository(self,e):
        pass
    
    def OnAddProject(self,e):
        repository = self.__selectedStoreNode()
        d = dialogs.ProjectPathDialog(self.getWindow())
        if d.ShowModal() == wx.ID_OK:
            log.info(_t('Add Project %s at: %s') % (d.getName(),d.getDir()))
            def addProject(monitor):
                facade2.manager.addProject(repository,d.getName(),d.getDir(),monitor)
            framework.runProgressDialog(self.getWindow(),_t('Add Project'), addProject) 
        d.Destroy()
        
    def OnSetProjectPath(self,e):
        pass
        
    def OnCommit(self,e):
        framework.runProgressDialog(self.getWindow(),_t('Add Project'), self._testMonitor) 
        
    def _testMonitor(self,monitor):
        monitor.beginTask('a',100)
        count = 0
        while count < 100:
            if monitor.isCanceled():
                print 'canceled testMonitor:',count
                break
            count += 1
            wx.MilliSleep(50)
            print 'testMonitor:',count
            monitor.setTaskName('t:' + str(count))
            monitor.worked(1)
 
        monitor.done()
        
    def OnUpdate(self,e):
        pass

    def __selectedStoreNode(self):
        selected=self.__storeNodeTree.GetSelection()
        if not selected:
            return None
        return self.__storeNodeTree.GetItemPyData(selected)
    
    def __addTreeItem(self,node):
        """
        __addTreeItem(StoreNode node)
        
         把一个StoreNode添加到树上,每一个树节点还设置了wx.TreeItemData,内容就是node本身
         另外tree为每一个节点增加一个适配器属性用来存储TreeItemId:_adapter_RepositoryView_treeItemId 
        """
        if node.type()==resource_type.ROOT:
            treeItemId = self.__storeNodeTree.AddRoot(u"root" ,data=wx.TreeItemData(node))
        else:
            treeItemId = self.__storeNodeTree.AppendItem(node.parent()._adapter_RepositoryView_treeItemId, node.name(),data=wx.TreeItemData(node))
            #self.__storeNodeTree.SortChildren(node.parent()._adapter_RepositoryView_treeItemId)
        
        node._adapter_RepositoryView_treeItemId=treeItemId


#---Workbench
class MainFrame(framework.Workbench):
    def __init__(self):
       framework.Workbench.__init__(self)
       
       self.addView(VIEW_ID_NAVIGATOR,LocalWorkspaceView(self))
       self.addView(VIEW_ID_REPOSITORY,RepositoryView(self))
       self.addView(VIEW_ID_LOG,self.createLogView())
       
       #'resources',images.perspective_icon_resource.loadBmp(32,32)
       self.addPerstectiveInfo(PERSTECTIVE_ID_RESOURCES,self.createResourcePerstectiveInfo())
       
       self.activatePerstective(PERSTECTIVE_ID_RESOURCES)
       
    def createResourcePerstectiveInfo(self):
        result = framework.PerstectiveInfo(_("resources"),images.perspective_icon_resource.loadBmp(32,32))
        result.addViewPaneInfo(VIEW_ID_NAVIGATOR, aui.PaneInfo().Caption(_("navigator")).Top()
            .CloseButton(False).Floatable(False).MinSize((100,400)))

        result.addViewPaneInfo(VIEW_ID_REPOSITORY,aui.PaneInfo().Caption(_("reposiroty")).Top()
           .CloseButton(False).Floatable(False))
        
        result.addViewPaneInfo(VIEW_ID_LOG,aui.PaneInfo().Caption(_t("log")).Center()
           .CloseButton(False).Floatable(False))

        return result
 
    def createLogView(self):
        logView = LogView(self)
        log.addHandler(LogViewHandler(logView))
        return logView
 
    def OnCloseWindow(self, event):
        self.Destroy()
        
#---memento
def openMemento():
    """
    提供shelve.open的便利访问，返回和shelve.open一样
    需要客户程序自己close
    """
    os2.makeFileDirs(config._mementoDbFilePath)
    result=shelve.open(config._mementoDbFilePath)
    return result

def main():
    app=wx.App(False)

    #wx.Log_SetActiveTarget(wx.LogStderr())#可以抑制获取图标时弹出错误消息匡但无excpetion的情况,或用wx.LogNull在程序中禁止一部分程序的异常消息
    memento = openMemento()
    global workbench 
    mainFrame = MainFrame()
    mainFrame.Show(True)
    app.SetTopWindow(mainFrame)
    app.MainLoop()
    
    memento.close()

_t=i18n.t_
 
VIEW_ID_NAVIGATOR='view.navigator'
VIEW_ID_REPOSITORY='view.repository'
VIEW_ID_LOG='view.log'
PERSTECTIVE_ID_RESOURCES='perstective.resources'
